﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;

using DNA;
using TJADRICD.CollaborativeDesignPlugin.Form;
using TJADRICD.CollaborativeDesignPlugin.Function;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using DBTransMan = Autodesk.AutoCAD.DatabaseServices.TransactionManager;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.PlottingServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

namespace TJADRICD.CollaborativeDesignPlugin.Function
{
    public static class Function_Publish
    {
        public static void CheckPlotFile()
        {
            Dictionary<String, String> list = Function_Registry.GetOptions();
            String PrinterConfigDir = list["PrinterConfigDir"];
            String PrinterDescDir = list["PrinterDescDir"];
            String PrinterStyleSheetDir = list["PrinterStyleSheetDir"];

            Boolean flag_copy = false;


            if (flag_copy)
            {
                FileInfo ApplicationPath = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
                DirectoryInfo Plotters = new DirectoryInfo(ApplicationPath.Directory.FullName + @"\" + "Plotters");

                Dictionary<String, String>.Enumerator enumerator = Data.MachineInfo.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    String machine = enumerator.Current.Value; 
                    MD5 md5Hasher = MD5.Create();
                    FileInfo src_pc3_file = new FileInfo(Plotters.FullName + @"\" + machine);
                    FileInfo src_pmp_file = new FileInfo(Plotters.FullName + @"\" + machine.Replace(".pc3", ".pmp"));
                    FileInfo dst_pc3_file = new FileInfo(PrinterConfigDir + @"\" + src_pc3_file.Name);
                    FileInfo dst_pmp_file = new FileInfo(PrinterDescDir + @"\" + src_pmp_file.Name);
                    if (!dst_pc3_file.Exists)
                    {
                        src_pc3_file.CopyTo(dst_pc3_file.FullName, true);
                    }

                    byte[] data1 = md5Hasher.ComputeHash(src_pc3_file.OpenRead());

                    byte[] data2 = md5Hasher.ComputeHash(dst_pc3_file.OpenRead());
                    StringComparer c = StringComparer.OrdinalIgnoreCase;

                    if (c.Compare(System.Text.Encoding.Default.GetString(data1), System.Text.Encoding.Default.GetString(data2)) != 0)
                    {
                        src_pc3_file.CopyTo(dst_pc3_file.FullName, true);
                    }

                    if (!dst_pmp_file.Exists)
                    {
                        src_pmp_file.CopyTo(dst_pmp_file.FullName, true);
                    }

                    data1 = md5Hasher.ComputeHash(src_pmp_file.OpenRead());

                    data2 = md5Hasher.ComputeHash(dst_pmp_file.OpenRead());

                    if (c.Compare(System.Text.Encoding.Default.GetString(data1), System.Text.Encoding.Default.GetString(data2)) != 0)
                    {
                        src_pmp_file.CopyTo(dst_pmp_file.FullName, true);
                    }
                }
            }
        }

        public static void PublishSingle(Database db, String MachineName)
        {
            String PaperName;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Transaction tr = db.TransactionManager.StartTransaction();
            String val = null;

            using (tr)
            {
                Dictionary<string, ObjectId> dctSign = new Dictionary<string, ObjectId>();
                Dictionary<string, AttributeReference> dctSignInfo = new Dictionary<string, AttributeReference>();
                BlockTable btToPublish = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                double frameScale = 0;
                BlockReference frame = null;
                BlockTableRecord btrToPublish = tr.GetObject(btToPublish[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                foreach (ObjectId id in btToPublish)
                {
                    BlockTableRecord btr2 = tr.GetObject(id, OpenMode.ForRead) as BlockTableRecord;
                    if (CommandFrame.IsVersionType(btr2.Name))
                    {
                        ObjectIdCollection ids = btr2.GetBlockReferenceIds(true, true);
                        foreach (ObjectId id2 in ids)
                        {
                            BlockReference br = tr.GetObject(id2, OpenMode.ForRead) as BlockReference;
                            frame = br;
                            frameScale = br.ScaleFactors.X;
                        }
                    }
                }
                if (frame == null)
                {
                    return;
                }
                try
                {
                    AttributeCollection ac = frame.AttributeCollection;
                    int iCount = 10;
                    foreach (ObjectId id in ac)
                    {

                        AttributeReference ar = tr.GetObject(id, OpenMode.ForWrite) as AttributeReference;
                        if (ar.Tag.EndsWith("SignPos") && (!ar.TextString.StartsWith(" ")) && (ar.TextString != ""))
                        {
                            if (ar.TextString == "hand")
                            {
                                ar.TextString = "";
                            }
                            else
                            {
                                dctSignInfo.Add(ar.TextString + iCount.ToString(), ar);
                                ++iCount;
                            }
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show("Error before publish 1" + ex.ToString());
                }

                try
                {
                    foreach (KeyValuePair<string, AttributeReference> kvpSign in dctSignInfo)
                    {
                        string signerName = kvpSign.Key.Substring(0, kvpSign.Key.Length - 2);
                        RasterImageDef realSignDef = null;

                        ObjectId DicId = RasterImageDef.GetImageDictionary(db);
                        if (DicId.IsNull)
                        {
                            DicId = RasterImageDef.CreateImageDictionary(db);
                        }
                        DBDictionary imageDic = tr.GetObject(DicId, OpenMode.ForWrite) as DBDictionary;

                        if (imageDic.Contains("RSB_" + signerName))
                        {
                            ObjectId tempId = imageDic.GetAt("RSB_" + signerName);
                            realSignDef = tr.GetObject(tempId, OpenMode.ForWrite) as RasterImageDef;
                        }
                        else
                        {
                            realSignDef = new RasterImageDef();
                            realSignDef.SourceFileName = Config.HandwritingPath + Function_Hash.GetNameMD5(signerName) + ".jpg";
                            realSignDef.Load();
                            realSignDef.ImageModified = true;
                            realSignDef.ResolutionUnits = Unit.Millimeter;
                            imageDic.SetAt("RSB_" + signerName, realSignDef);
                            tr.AddNewlyCreatedDBObject(realSignDef, true);
                        }
                        AttributeReference arSign = kvpSign.Value;
                        RasterImage imageRef = new RasterImage();
                        imageRef.ImageDefId = realSignDef.ObjectId;
                        double scale1 = 0;
                        double scale2 = 0;
                        if ((arSign.Rotation == Math.PI / 2) || (arSign.Rotation == 270))
                        {
                            scale1 = 16 * frameScale / realSignDef.Size.X;
                            scale2 = 8 * frameScale / realSignDef.Size.Y;
                        }
                        else
                        {
                            scale1 = 20 * frameScale / realSignDef.Size.X;
                            scale2 = 10 * frameScale / realSignDef.Size.Y;
                        }
                        double realScale = scale1 > scale2 ? scale2 : scale1;
                        double lengthX = realSignDef.Size.X * realScale * 0.84;
                        double lengthY = realSignDef.Size.Y * realScale * 0.84;
                        double positionX = 0, positionY = 0;
                        if ((arSign.Rotation == Math.PI / 2) || (arSign.Rotation == 270))
                        {
                            positionX = arSign.Position.X - frameScale * 0.3;
                            positionY = arSign.Position.Y + frameScale * 0.28;
                        }
                        else
                        {
                            positionX = arSign.Position.X + (20 * frameScale - lengthX) / 2;
                            positionY = arSign.Position.Y + (10 * frameScale - lengthY) / 2;
                            if (arSign.Tag == "DrawnBySignPos")
                            {
                                positionY -= 0.3 * frameScale;
                            }
                        }
                        Point3d posInsert = new Point3d(positionX, positionY, arSign.Position.Z);
                        imageRef.Orientation = new CoordinateSystem3d(posInsert, new Vector3d(lengthX, 0, 0), new Vector3d(0, lengthY, 0));
                        imageRef.Rotation = arSign.Rotation;
                        btrToPublish.AppendEntity(imageRef);
                        tr.AddNewlyCreatedDBObject(imageRef, true);
                        arSign.TextString = "";
                    }
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show("Error before publish 2"+ex.ToString());
                }

                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);

                PlotInfo pi = new PlotInfo();
                pi.Layout = btr.LayoutId;
                PlotSettings ps = new PlotSettings(lo.ModelType);

                ps.CopyFrom(lo);
                PlotSettingsValidator psv = PlotSettingsValidator.Current;

                psv.SetUseStandardScale(ps, true);
                psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
                psv.SetPlotCentered(ps, true);
                System.Collections.Specialized.StringCollection clo2 = psv.GetPlotDeviceList();

                System.Collections.Specialized.StringCollection clo3 = psv.GetCanonicalMediaNameList(ps);

                psv.RefreshLists(ps);
                foreach (String PN in clo3)
                {
                    String mediana = String.Empty;
                    try
                    {
                        mediana = psv.GetLocaleMediaName(ps, PN);
                    }
                    catch
                    {
                        // MessageBox.Show(ex.ToString());
                    }
                    Tools.WriteMessageWithReturn(PN);
                    Tools.WriteMessageWithReturn(mediana);

                }
                System.Collections.Specialized.StringCollection sl = psv.GetPlotStyleSheetList();



                Double minX = 0;
                Double minY = 0;
                Double maxX = 0;
                Double maxY = 0;


                PaperName = "";
                foreach (ObjectId blockid in bt)
                {
                    BlockTableRecord record = (BlockTableRecord)tr.GetObject(blockid, OpenMode.ForRead);
                    if (record.Name.StartsWith("TJAD_TK_A") || record.Name.StartsWith("TJAD_TK_N"))
                    {

                        ObjectIdCollection blockRefIds = record.GetBlockReferenceIds(true, true);
                        Tools.WriteMessageWithReturn(blockRefIds.Count.ToString());
                        foreach (ObjectId blockRefId in blockRefIds)
                        {
                            String record_name = String.Empty;
                            if (record.Name.StartsWith("TJAD_TK_"))
                            {
                                record_name = record.Name;
                            }
                            Dictionary<String, String>.Enumerator enumerator = Data.PaperInfo.GetEnumerator();
                            while (enumerator.MoveNext())
                            {
                                String key = enumerator.Current.Key;
                                key = key + "_";
                                if (record_name.StartsWith(key))
                                {
                                    PaperName = enumerator.Current.Value;
                                }
                            }
                            Tools.WriteMessageWithReturn(record.Name);
                            Tools.WriteMessageWithReturn(MachineName);
                            Tools.WriteMessageWithReturn(PaperName);
                            BlockReference blockRef = (BlockReference)tr.GetObject(blockRefId, OpenMode.ForWrite);
                            try
                            {
                                AttributeCollection atc = blockRef.AttributeCollection;
                                foreach (ObjectId oid in atc)
                                {
                                    AttributeReference atr = tr.GetObject(oid, OpenMode.ForRead) as AttributeReference;
                                    if (atr.Tag == "SheetTitleChinese")
                                    {
                                        val = atr.TextString;
                                    }
                                }
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }

                            String ctbName = "TJAD_PlotStyle.ctb";


                            psv.GetPlotStyleSheetList();
                            try
                            {
                                psv.SetCurrentStyleSheet(ps, ctbName);
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show("   " + ex.ToString());
                                Tools.WriteMessageWithReturn(ex.ToString());
                            }

                            try
                            {
                                Extents3d ext = blockRef.GeometricExtents;
                                Point3d PT1 = ext.MaxPoint;
                                Point3d PT2 = ext.MinPoint;
                                minX = System.Math.Min(PT1.X, PT2.X);
                                minY = System.Math.Min(PT1.Y, PT2.Y);
                                maxX = System.Math.Max(PT1.X, PT2.X);
                                maxY = System.Math.Max(PT1.Y, PT2.Y);

                                Extents2d e2d = new Extents2d(minX, minY, maxX, maxY);
                                psv.SetPlotWindowArea(ps, e2d);
                                Tools.WriteMessageWithReturn(ext.ToString());
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show("   " + ex.ToString());
                                Tools.WriteMessageWithReturn("No EXTENTS");
                            }

                        }
                    }
                }
                try
                {
                   // psv.SetPlotConfigurationName(ps, "DWG To PDF.pc3", "ANSI_B_(11.00_x_17.00_Inches)");
                    psv.SetPlotConfigurationName(ps, MachineName, PaperName);
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ps.ToString() + "   " + MachineName + "   " + PaperName+ "   "+ex.ToString());

                }
                psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Window);
                psv.SetPlotRotation(ps, PlotRotation.Degrees090);

                pi.OverrideSettings = ps;

                PlotInfoValidator piv = new PlotInfoValidator();
                piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
                piv.Validate(pi);

                PlotEngine pe = PlotFactory.CreatePublishEngine();
                using (pe)
                {
                    PlotProgressDialog ppd = new PlotProgressDialog(false, 1, true);
                    using (ppd)
                    {
                        ppd.set_PlotMsgString(
                          PlotMessageIndex.DialogTitle,
                          "正在打印"//"Custom Plot Progress"
                        );
                        ppd.set_PlotMsgString(
                          PlotMessageIndex.CancelJobButtonMessage,
                          "取消当前打印"//"Cancel Job"
                        );
                        ppd.set_PlotMsgString(
                          PlotMessageIndex.CancelSheetButtonMessage,
                          "取消本页打印"//"Cancel Sheet"
                        );
                        ppd.set_PlotMsgString(
                          PlotMessageIndex.SheetSetProgressCaption,
                          "打印集合进度"//"Sheet Set Progress"
                        );
                        ppd.set_PlotMsgString(
                          PlotMessageIndex.SheetProgressCaption,
                          "打印页进度"//"Sheet Progress"
                        );
                        ppd.LowerPlotProgressRange = 0;
                        ppd.UpperPlotProgressRange = 100;
                        ppd.PlotProgressPos = 0;

                        ppd.OnBeginPlot();
                        ppd.IsVisible = true;
                        pe.BeginPlot(ppd, null);
                        FileInfo fi = new FileInfo(db.Filename);
                        DirectoryInfo di = fi.Directory;
                        pe.BeginDocument(pi, doc.Name, null, 1, true, di.Parent.Parent.FullName + @"\PB\" + fi.Name.Substring(0, (fi.Name.Length - 4)));

                        // Which contains a single sheet

                        ppd.OnBeginSheet();

                        ppd.LowerSheetProgressRange = 0;
                        ppd.UpperSheetProgressRange = 100;
                        ppd.SheetProgressPos = 0;

                        PlotPageInfo ppi = new PlotPageInfo();
                        pe.BeginPage(ppi, pi, true, null);
                        pe.BeginGenerateGraphics(null);
                        pe.EndGenerateGraphics(null);

                        // Finish the sheet
                        pe.EndPage(null);
                        ppd.SheetProgressPos = 100;
                        ppd.OnEndSheet();

                        // Finish the document

                        pe.EndDocument(null);

                        // And finish the plot

                        ppd.PlotProgressPos = 100;
                        ppd.OnEndPlot();
                        pe.EndPlot(null);


                    }
                }
                Tools.WriteMessageWithReturn("finish");
                FileInfo fi2 = new FileInfo(db.Filename);
                FileInfo fini = new FileInfo(fi2.Directory.Parent.Parent.FullName + @"\PB\" + fi2.Name.Substring(0, (fi2.Name.Length - 4)) + ".ini");

                Extern.WritePrivateProfileString("Name", fi2.Name.Substring(0, (fi2.Name.Length - 4)), val, fini.FullName);

                fini.Attributes |= FileAttributes.Hidden;
            }
        }
    }
}
